package com.jacky.ocr_plugin;

import android.app.Activity;
import android.app.Application;
import android.os.Build;
import android.os.Bundle;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.lifecycle.Lifecycle;

import com.jacky.ocr_plugin.camera.OcrCamera2HandlerImpl;
import com.jacky.util.OcrLogger;
import com.jacky.util.PermissionUtil;

import java.lang.ref.WeakReference;

import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
import io.flutter.embedding.engine.plugins.lifecycle.HiddenLifecycleReference;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugin.platform.PlatformViewRegistry;
import io.flutter.view.TextureRegistry;

/** OcrPlugin */
public class OcrPlugin implements FlutterPlugin, ActivityAware{

  private OcrLifecycleCallbacks ocrLifecycleCallbacks;

  private OcrCamera2HandlerImpl methodCallHandler;
  private @Nullable FlutterPluginBinding flutterPluginBinding;

  /** Plugin registration embedding v1 */
  public void registerWith(PluginRegistry.Registrar registrar) {
    new OcrPlugin().onAttachedToV1(registrar);
  }

  private void onAttachedToV1(PluginRegistry.Registrar registrar) {
    Shared.registrar = registrar;
    onAttachedToEngines(registrar.platformViewRegistry(), registrar.messenger(), registrar.activity());
    startActivityListener(registrar.activity(),
            registrar.messenger(),
            registrar::addRequestPermissionsResultListener,
            registrar::addActivityResultListener,
            registrar.textures(),null);
  }

  /** Plugin start for both embedding v1 & v2 */
  private void  onAttachedToEngines(PlatformViewRegistry platformViewRegistry, BinaryMessenger messenger , Activity activity){
    if (activity != null) {
      Shared.currentActivity = new WeakReference<>(activity);
    }
    OcrLogger.setLogLevel(BuildConfig.DEBUG ? OcrLogger.VERBOSE : OcrLogger.ERROR);
    OcrLogger.d("tag","flutter to android, ocrPlugin onAttachedToEngines");
    platformViewRegistry.registerViewFactory("com.jacky.util/ocr_view"
            , new OcrRectViewFactory(messenger));
  }
  
  private Activity getActivity(){
    if(Shared.currentActivity == null) return null;
    return Shared.currentActivity.get();
  }

  /** Plugin registration embedding v2 */
  @Override
  public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
    OcrLogger.d("tag","flutter to android, ocrPlugin onAttachedToEngine");
    this.flutterPluginBinding = flutterPluginBinding;
    onAttachedToEngines(flutterPluginBinding.getPlatformViewRegistry()
            , flutterPluginBinding.getBinaryMessenger()
            , getActivity());
  }

  @Override
  public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
    flutterPluginBinding = null;
  }


  @Override
  public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) {
    registerLifecycle(binding.getActivity());
    Shared.binding = binding;
    HiddenLifecycleReference reference = (HiddenLifecycleReference) binding.getLifecycle();
    startActivityListener(binding.getActivity(),
            flutterPluginBinding != null ? flutterPluginBinding.getBinaryMessenger() : null,
            binding::addRequestPermissionsResultListener,
            binding::addActivityResultListener,
            flutterPluginBinding != null ?flutterPluginBinding.getTextureRegistry() : null,
            reference.getLifecycle());
  }

  @Override
  public void onDetachedFromActivityForConfigChanges() {
    Shared.binding = null;
  }

  @Override
  public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) {
    Shared.binding = binding;
    HiddenLifecycleReference reference = (HiddenLifecycleReference) binding.getLifecycle();
    startActivityListener(binding.getActivity(),
            flutterPluginBinding != null ? flutterPluginBinding.getBinaryMessenger() : null,
            binding::addRequestPermissionsResultListener,
            binding::addActivityResultListener,
            flutterPluginBinding != null ?flutterPluginBinding.getTextureRegistry() : null,
            reference.getLifecycle());
  }


  @Override
  public void onDetachedFromActivity() {
    Shared.binding = null;
    if(Shared.currentActivity != null){
      unRegisterLifecycle(Shared.currentActivity.get());
    }
    if (methodCallHandler != null) {
      if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
        methodCallHandler.stopListening();
      }
      methodCallHandler = null;
    }
  }

  private void startActivityListener(Activity activity,
                                     BinaryMessenger messenger,
                                     PermissionUtil.PermissionsRegistry permissionsRegistry,
                                     PermissionUtil.ActivityForResultRegistry activityForResultRegistry,
                                     TextureRegistry textureRegistry,
                                     @Nullable Lifecycle lifecycle){
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
      // If the sdk is less than 21 (min sdk for Camera2) we don't register the plugin.
      return;
    }
    methodCallHandler = new OcrCamera2HandlerImpl(
            activity,
            messenger,
            textureRegistry,
            lifecycle,
            permissionsRegistry,
            activityForResultRegistry);
  }
  
  private void registerLifecycle(Activity activity){
    if(activity == null || Shared.isRegisterLifecycle) return;
    Shared.currentActivity = new WeakReference<>(activity);
    activity.getApplication().registerActivityLifecycleCallbacks(ocrLifecycleCallbacks = new OcrLifecycleCallbacks());
    Shared.isRegisterLifecycle = true;
  }
  
  private void unRegisterLifecycle(Activity activity){
    if(activity != null && ocrLifecycleCallbacks != null){
      Shared.isRegisterLifecycle = false;
      activity.getApplication().registerActivityLifecycleCallbacks(ocrLifecycleCallbacks);
    }
  }
  
  private static class OcrLifecycleCallbacks implements Application.ActivityLifecycleCallbacks{
    @Override
    public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) {
      Shared.currentActivity = new WeakReference<>(activity) ;
    }

    @Override
    public void onActivityStarted(@NonNull Activity activity) {
      Shared.currentActivity = new WeakReference<>(activity) ;
    }

    @Override
    public void onActivityResumed(@NonNull Activity activity) {
      Shared.currentActivity = new WeakReference<>(activity) ;
    }

    @Override
    public void onActivityPaused(@NonNull Activity activity) {

    }

    @Override
    public void onActivityStopped(@NonNull Activity activity) {

    }

    @Override
    public void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState) {

    }

    @Override
    public void onActivityDestroyed(@NonNull Activity activity) {
      if(Shared.currentActivity.get() == activity) Shared.currentActivity.clear();
    }
  }
}
